// Oneself
#include "can.h"
#include "motor_control.h"
#include "control_config.h"

int16_t * dec_param_reg;

CAN_HandleTypeDef hcan;
BSP_CAN_Typedef bsp_can = {0};

#define CAN_RX0_INT_ENABLE 1

ErrorStatus BSP_CAN_Init(void)
{
    // HAL_CAN_DeInit(&hcan);
    hcan.Instance = CAN1;
    hcan.Init.Prescaler = 8;                  /* 分频系数(Fdiv)为brp+1 */
    hcan.Init.Mode = CAN_MODE_NORMAL;          /* 模式设置 */
    hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;      /* 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1TQ~CAN_SJW_4TQ */
    hcan.Init.TimeSeg1 = CAN_BS1_9TQ;          /* tbs1范围CAN_BS1_1TQ~CAN_BS1_16TQ */
    hcan.Init.TimeSeg2 = CAN_BS2_8TQ;          /* tbs2范围CAN_BS2_1TQ~CAN_BS2_8TQ */
    hcan.Init.TimeTriggeredMode = DISABLE;      /* 非时间触发通信模式 */
    hcan.Init.AutoBusOff = ENABLE;              /* 软件自动离线管理 */
    hcan.Init.AutoWakeUp = ENABLE;              /* 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) */
    hcan.Init.AutoRetransmission = DISABLE;      /* 禁止报文自动传送 */
    hcan.Init.ReceiveFifoLocked = DISABLE;      /* 报文不锁定,新的覆盖旧的 */
    hcan.Init.TransmitFifoPriority = DISABLE; /* 优先级由报文标识符决定 */
    if (HAL_CAN_Init(&hcan) != HAL_OK)
    {
      Error_Handler();
    }

    CAN_FilterTypeDef sFilterConfig;
    /* 配置CAN过滤器 */
    sFilterConfig.FilterBank = 0; /* 过滤器0 */
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh = 0x0000; /* 32位ID */
    sFilterConfig.FilterIdLow = 0x0000;
    sFilterConfig.FilterMaskIdHigh = 0x0000; /* 32位MASK */
    sFilterConfig.FilterMaskIdLow = 0x0000;
    sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; /* 过滤器0关联到FIFO0 */
    sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;       /* 激活滤波器0 */

    /* 过滤器配置 */
    if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
    {
      Error_Handler();
    }

    /* 使用中断接收 */
    if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
    {
        Error_Handler();
    }

    /* 启动CAN外围设备 */
    if (HAL_CAN_Start(&hcan) != HAL_OK)
    {
      Error_Handler();
    }

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    dec_param_reg = (int16_t *)&g_motor_config;
    return SUCCESS;
}

void HAL_CAN_MspInit(CAN_HandleTypeDef *canHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if (canHandle->Instance == CAN1)
    {
        /* CAN1 clock enable */
        __HAL_RCC_CAN1_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();
        /**CAN GPIO Configuration
        PB8     ------> CAN_RX
        PB9     ------> CAN_TX
        */
        GPIO_InitStruct.Pin = GPIO_PIN_8;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_9;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        __HAL_AFIO_REMAP_CAN1_2();

#if CAN_RX0_INT_ENABLE

        HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 3, 0);         /* 抢占优先级3，子优先级0 */
        HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);                 /* 使能CAN中断 */
#endif
    }
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef *canHandle)
{
    if (canHandle->Instance == CAN1)
    {
        /* Peripheral clock disable */
        __HAL_RCC_CAN1_CLK_DISABLE();

        /**CAN GPIO Configuration
        PB8     ------> CAN_RX
        PB9     ------> CAN_TX
        */
        HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8 | GPIO_PIN_9);

        /* CAN1 interrupt Deinit */
        HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
    }
}


/**
 * @brief       CAN 发送一组数据
 *   @note      发送格式固定为: 标准ID, 数据帧
 * @param       id      : 标准ID(11位)
 * @param       msg     : 数据指针
 * @param       len     : 数据长度
 * @retval      发送状态 0, 成功; 1, 失败;
 */
ErrorStatus can_send_msg(uint8_t *cmd, uint8_t len)
{
    uint16_t t = 0;
    uint32_t TxMailbox;
    uint8_t i = 0, j = 0, k = 0, l = 0, packNum = 0;

    // 除去ID地址和功能码后的数据长度
    j = len - 2;

    // 发送数据
    while(i < j)
    {
        // 数据个数
        k = j - i;

        // 填充缓存
        bsp_can.CanTx.StdId = 0x00;
        bsp_can.CanTx.ExtId = ((uint32_t)cmd[0] << 8) | (uint32_t)packNum;
        bsp_can.TXData[0] = cmd[1];
        bsp_can.CanTx.IDE = CAN_ID_EXT;
        bsp_can.CanTx.RTR = CAN_RTR_DATA;

        // 小于8字节命令
        if(k < 8)
        {
            for(l=0; l < k; l++,i++) { bsp_can.TXData[l + 1] = cmd[i + 2]; } bsp_can.CanTx.DLC = k + 1;
        }
        // 大于8字节命令，分包发送，每包数据最多发送8个字节
        else
        {
            for(l=0; l < 7; l++,i++) { bsp_can.TXData[l + 1] = cmd[i + 2]; } bsp_can.CanTx.DLC = 8;
        }

        // 发送数据
        // CAN_Transmit(CAN1, (CanTxMsg *)(&can.CAN_TxMsg));
        if (HAL_CAN_AddTxMessage(&hcan, &bsp_can.CanTx, &bsp_can.TXData[0], &TxMailbox) != HAL_OK) /* 发送消息 */
        {
            return ERROR;
        }
    
        while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan) != 3) /* 等待发送完成,所有邮箱为空 */
        {
            t++;
    
            if (t > 0xFFF)
            {
                HAL_CAN_AbortTxRequest(&hcan, TxMailbox); /* 超时，直接中止邮箱的发送请求 */
                return ERROR;
            }
        }

        // 记录发送的第几包的数据
        ++packNum;
    }
    return SUCCESS;
}



